#ifndef LENSTRAYLOADER_H
#define LENSTRAYLOADER_H

#include "AxisModule/singleaxis.h"
#include "CompositeElement/sccylinder.h"
#include "Tray/lenstraymap.h"
#include "Tray/trayconfig.h"
#include "VisionLocation/visionlocation.h"
#include "VisionManager/visionmanager.h"
#include "lenstraybuffer.h"
#include "namedefinition.h"
#include "systemCore/worker.h"
#include "workers/BonderHead/bonderheadconfig.h"

class LensTrayLoader : public Worker
{
    Q_OBJECT
public:
    LensTrayLoader(LensTrayModuleConfig *ltConfig,
                   LensTrayModuleState *ltState,
                   LensTrayMagazine *ltMag,
                   LensTrayBuffer *ltBuffer,
                   TrayConfig *lensTrayConfig,
                   LensTrayMap *lensTrayMap,
                   QObject *parent = nullptr);

    void setBHConfig(BonderHeadConfig *bhConfig);

    PrOffset getLensPrOffset(int index);
    PrOffset getLTVacancyPrOffset(int index);

    void correctPrOffset(PrOffset &prOffset);

    bool gotLens() const;
    void resetGotLens();
    void setLensState(QPoint index, LensTrayMaterialData::MaterialState state);
    QPoint getLastLensIndex() const;
    PrOffset getLastLensOffset() const;
    TrayMap *getTrayMap() const;

    // Worker interface
protected:
    virtual void initEventHandle() override;
    virtual void startEventHandle(const WorkerEvent &event) override;
    virtual void stopEventHandle() override {}
    virtual void allWorkerStopped() override;
    virtual void purgeEventHandle() override;
    virtual void resetEventHandle() override;
    virtual void homeWorker(bool moveToReadyPosAfterHome) override;

    // 自动运行逻辑
public slots:
    void loadTray();
    void unloadTray();
    void kickerAndClampToReady();
    void ltMagArrivedFirstInUseTrayPos();
    void getLens();
    void ltBufferStopped();

    // 手动调试操作
public slots:
    void lensTrayBufferManuallyLoadTray();
    void manuallyLoadTray();
    void manuallyUnloadTray();
    void synchronizeHasTray();

    void startLoadUnloadTrayLoopTest(int times);
    void doDummyWork();
    void stopLoadUnloadTrayLoopTest();
    void resetLoadUnloadTrayLoopTest();
    void loadUnloadTrayLoopTestFinished();

    void moveToPrPos(int unitRowIndex, int unitColumnIndex, int rowIndex, int columnIndex);
    void moveToPerformLensPr(int unitRowIndex, int unitColumnIndex, int rowIndex, int columnIndex);
    void moveToPerformVacancyPr(int unitRowIndex, int unitColumnIndex, int rowIndex, int columnIndex);

    void resetRowColumnIndex();

private:
    void loadTrayImpl();
    void verifyLensTrayMap();
    void unloadTrayImpl();
    void moveToPrPosImpl(int unitColumnIndex, int columnIndex);
    void moveToPrPosImpl(int columnIndex);
    void handleStop();

private:
    LensTrayModuleConfig *ltConfig;
    LensTrayModuleState *ltState;
    LensTrayMagazine *ltMag;
    LensTrayBuffer *ltBuffer;
    TrayConfig *lensTrayConfig;
    LensTrayMap *lensTrayMap;

    BonderHeadConfig *bhConfig = nullptr;

    SCAxis *ltLoaderBelt;
    SingleAxis *ltLoaderBeltZ;
    SingleAxis *ltLoaderTrackX;
    SingleAxis *ltBufferBeltZ;
    SCCylinder *ltlClamp;
    SCCylinder *ltlUnloadKicker;
    SCCylinder *ltlLeftDam;
    SCDI *ltLoaderStageSensor;
    SCDI *ltLoaderLeftSensor;

    VisionLocation *ltLensLocation;
    VisionLocation *ltVacancyLocation;

    bool hasSynchronizeHasTray = false;
    bool isLtMagArrivedFirstInUseTrayPos = false;
    bool isLtBufferStopped = false;
    int currentColumnIndex = 0;
    bool m_gotLens = false;
    QPoint lastLensIndex;
    PrOffset lastLensOffset;

    SCAxis::Direction beltRunDir;
};

#endif    // LENSTRAYLOADER_H
